<?php
/*----------------------------------------------------------------------------------------------
Kit Applicatif PHP
Noyau générique d'applications PHP / generic kernel for PHP applications
noyau 0.4 / PHP 4
http://code.fredbird.org/wak

API autour des dates et du temps


file version 2005-05-30 12:34:54
----------------------------------------------------------------------------------------------*/

class waktimemanager extends wakCoreComponent {
/*----------------------------------------------------------------------------------------------
                                                                           parametres par defaut
----------------------------------------------------------------------------------------------*/
	var $default_parameters=array(
		// heures a afficher dans un select
		"selectHours" => "00;01;02;03;04;05;06;07;08;09;10;11;12;13;14;15;16;17;18;19;20;21;22;23",
		// minutes a afficher dans un select
		"selectMinutes" => "00;05;10;15;20;25;30;35;40;45;50;55",
		// secondes a afficher dans un select
		"selectSeconds" => "00;05;10;15;20;25;30;35;40;45;50;55",
		// annee de debut dans un select
		"selectYearStart" => 2000,
		// annee de fin dans un select
		"selectYearEnd" => 2010,
		'labels'=>	array(
			"seconds" => "secondes",
			"minutes" => "minutes",
			"hours" => "heure",
			"wday" => "jour",
			"weekday" => "jour",
			"mday" => "jour",
			"mon" => "mois",
			"month" => "mois",
			"year" => "année")
	);
	var $mois=array('','Janvier','Fevrier','Mars','Avril','Mai','Juin',
		'Juillet','Aout','Septembre','Octobre','Novembre','Decembre');
	var $jours=array('Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi','Dimanche');
	var $formats=array(
		"php_timestamp" => array( "from" => "_fromPhpTimestamp","to" => "_toPhpTimestamp")
		, "php_getdate" => array( "from" => "_fromPhpGetDate","to" => "_toGetDate")
		, "mysql_date" => array( "from" => "_fromMysqlDate","to" => "_toMysqlDate")
		, "mysql_datetime" => array( "from" => "_fromMysqlDateTime","to" => "_toMysqlDateTime")
		, "mysql_timestamp" => array( "from" => "_fromMysqlTimestamp","to" => "_toMysqlTimestamp")
		, 'fr_date' => array('from'=>'_fromFrDate','to'=>'_toFrDate')
		// , 'frdate' => array('from'=>'_fromFrDate','to'=>'_toFrDate')
	);
	/*var $labels=array(
		"seconds" => "secondes",
		"minutes" => "minutes",
		"hours" => "heure",
		"wday" => "jour",
		"weekday" => "jour",
		"mday" => "jour",
		"mon" => "mois",
		"month" => "mois",
		"year" => "année");*/
/*----------------------------------------------------------------------------------------------
                                                                           constructeur eventuel
----------------------------------------------------------------------------------------------*/
	/*function wak(& $controller) {
		// appel du constructeur parent
		$const=get_parent_class($this);
		parent::$const($controller);
		// suite
	}*/
/*---------------------------------------------------------------------------
                                                           methodes publiques
---------------------------------------------------------------------------*/
	// convertit une date d'un format à un autre
	function convert($format_sortie, $date=NULL, $format_entree=NULL) {
		//$this->_action("appel public convert($format_sortie, $date, $format_entree)");
		// si la date n'est pas fournie, utilisation de la derniere date
		if ($date===NULL) {
			$getdate=getdate();
			$format_entree="php_getdate";
		} else {
			// si le format n'est pas fourni on tente de le determiner
			if (!$format_entree and !$format_entree=$this->_getFormat($date)) {
				trigger_error("timemanager::convert : unable to determine date format for $date.");
				return false;
			}
			// conversion au format php_getdate
			$getdate=$this->_convertFrom($date,$format_entree);
		}
		// on enregistre le getdate obtenu
		$this->date=$getdate;
		// on convertit ensuite la date au format desire
		return $this->_convertTo($getdate,$format_sortie);
	}
   
	/* sensiblement egal a date()
	mais en franþais, et accepte d'autres formats que timestamp, et des dates anterieures Ó 1970
	caracteres de format : d D F H i s m M w Y y l
	attention : il est possible (probable) que la date d'origine ne contienne pas toutes les informations
	notamment le jour de la semaine etc
	*/
	function frDate($formatage, $date=NULL, $format_entree=NULL) {
		if ($date===NULL) $getdate=getdate();
		else {
			// determination du format
			if (!$format_entree and !$format_entree=$this->_getFormat($date)) {
				trigger_error("frdate : format incorrect");
				return false;
			}
			// conversion en getdate
			$getdate=$this->_convertFrom($date,$format_entree);
		}
		// insertion des elements de date dans la chaine de formatage
		// jour du mois sur deux chiffres
		$retour=str_replace("d",sprintf("%02d",$getdate['mday']),$formatage);
		// jour de la semaine textuel sur trois lettres
		$retour=str_replace("D",substr($this->jours[$getdate['wday']],0,3),$retour);
		// heures, sur 24, avec zero initial
		$retour=str_replace("H",sprintf("%02d",$getdate['hours']),$retour);
		// minutes avec zero initial
		$retour=str_replace("i",sprintf("%02d",$getdate['minutes']),$retour);
		// secondes avec zero initial
		$retour=str_replace("s",sprintf("%02d",$getdate['seconds']),$retour);
		// mois avec zero initial
		$retour=str_replace("m",sprintf("%02d",$getdate['mon']),$retour);
		// mois textuel sur trois lettres
		$retour=str_replace("M",substr($this->mois[$getdate['mon']],0,3),$retour);
		// jour de la semaine numerique
		$retour=str_replace("w",$getdate['wday'],$retour);
		// annee sur 4 chiffres
		$retour=str_replace("Y",$getdate['year'],$retour);
		// annee sur 2 chiffres
		$retour=str_replace("y",substr($getdate['year'],2),$retour);
		// jour de la semaine textuel complet
		$retour=str_replace("l",$this->jours[$getdate['wday']],$retour);
		// jour du mois textuel complet
		$retour=str_replace("F",$this->mois[$getdate['mon']],$retour);
		return $retour;
	}
	
	// recupere le numero de semaine d'une date donnée
	function getWeek($date=NULL) {
		if ($date==NULL) $date=getdate();
		// recup infos date du jour
		$table=$this->convert('php_getdate',$date);
		// recup jour de la semaine du premier jour de l'année
		$firstDay=$this->convert('php_timestamp',$table['year'].'-01-01');
		$tFirstDay=getdate($firstDay);
		//echo affvar($tFirstDay['wday']);
		return ceil(($table['yday']+$tFirstDay['wday'])/7);
		//echo affvar($table);
	}
	// recupere l'année d'une date donnée
	function getYear($date=NULL) {
		if ($date==NULL) $date=getdate();
		$table=$this->convert('php_getdate',$date);
		return $table['year'];
	}

	/* retourne une suite de select identifiant la date donnee
	les elements correspondents Ó ceux d'un format getdate, separes par des _
	(seconds minutes hours wday weekday mday mon month year)
	si label vaut true, les labels seront ajoutes */
	function formSelectDate($prefix="",$date=NULL,$elements="mday_mon_year", $label=NULL) {
		$retour="";
		// si la date n'est pas fournie, on garde la derniere utilisÚe
		if ($date==NULL) $date=getdate();
		else {
			// definition du format
			$format=$this->_getFormat($date);
			// conversion en tableau getdate
			$getdate=$this->_convertFrom($date,$format);
		}
		$elements=explode("_",$elements);
		// on parcourt la liste des elements dans l'ordre
		foreach($elements as $e) {
			$name=$prefix.$e;
			// affichage du label si necessaire
			if ($label) $retour.="<label for=\"$label\">".$this->parameters['labels'][$e]."</label>\n";
			// affichage du select
			$retour.="<select name=\"$name\" id=\"$name\">\n";
			switch ($e) {
			case "seconds":
				$selected=false;
				for ($f=0; $f<=59; $f++) {
					if (stristr($this->parameters['selectSeconds'],sprintf("%02d",$f))) {
						$retour.="<option value=\"".sprintf("%02d",$f)."\"";
						if ($f>=$getdate['seconds'] and !$selected) {
							$retour.=" selected"; $selected=true;
						}
						$retour.=">".sprintf("%02d",$f)."s</option>\n";
					}
				}
				break;
			case "minutes":
				$selected=false;
				for ($f=0; $f<=59; $f++) {
					if (stristr($this->parameters['selectMinutes'],sprintf("%02d",$f))) {
						$retour.="<option value=\"".sprintf("%02d",$f)."\"";
						if ($f>=$getdate['minutes'] and !$selected) {
							$retour.=" selected"; $selected=true;
						}
						$retour.=">".sprintf("%02d",$f)."mn</option>\n";
					}
				}
				break;
			case "hours":
				$selected=false;
				for ($f=0; $f<=23; $f++) {
					if (stristr($this->parameters['selectHours'],sprintf("%02d",$f))) {
						$retour.="<option value=\"".sprintf("%02d",$f)."\"";
						if ($f>=$getdate['hours'] and !$selected) {
							$retour.=" selected"; $selected=true;
						}
						$retour.=">".sprintf("%02d",$f)."h</option>\n";
					}
				}
				break;
			case "wday":
				for ($f=1; $f<=7; $f++) {
					$retour.="<option value=\"$f\"";
					if ($f==$getdate['wday']) $retour.=" selected";
					$retour.=">$f</option>\n";
				}
				break;
			case "weekday":
				for ($f=1; $f<=7; $f++) {
					$retour.="<option value=\"$f\"";
					if ($f==$getdate['wday']) $retour.=" selected";
					$retour.=">".$this->jours[$f]."</option>\n";
				}
				break;
			case "mday": // jour du mois
				for ($f=1; $f<=31; $f++) {
					$retour.="<option value=\"".sprintf("%02d",$f)."\"";
					if ($f==$getdate['mday']) $retour.=" selected";
					$retour.=">".sprintf("%02d",$f)."</option>\n";
				}
				break;
			case "mon":
				for ($f=1; $f<=12; $f++) {
					$retour.="<option value=\"".sprintf("%02d",$f)."\"";
					if ($f==$getdate['mon']) $retour.=" selected";
					$retour.=">".sprintf("%02d",$f)."</option>\n";
				}
				break;
			case "month":
				for ($f=1; $f<=12; $f++) {
					$retour.="<option value=\"".sprintf("%02d",$f)."\"";
					if ($f==$getdate['mon']) $retour.=" selected";
					$retour.=">".$this->mois[$f]."</option>\n";
				}
				break;
			case "year":
				for ($f=$this->parameters['selectYearStart']; $f<=$this->parameters['selectYearEnd']; $f++) {
					$retour.="<option value=\"$f\"";
					if ($f==$getdate['year']) $retour.=" selected";
					$retour.=">$f</option>\n";
				}
				break;
			} // fin du switch
			$retour.="</select>\n";
		}
		return $retour;
	}
	function catchSelectDate($prefix="",$format_sortie="php_getdate") {
		$getdate=array();
		// recup des donnees post
		//$fields=array('hours','minutes','seconds','mon','');
		if (isset($_POST[$prefix.'hours']))
			$getdate['hours']=intval($_POST[$prefix.'hours']);
		else $getdate['hours']=0;
		if (isset($_POST[$prefix.'minutes']))
			$getdate['minutes']=intval($_POST[$prefix.'minutes']);
		else $getdate['minutes']=0;
		if (isset($_POST[$prefix.'seconds']))
			$getdate['seconds']=intval($_POST[$prefix.'seconds']);
		else $getdate['seconds']=0;
		if (isset($_POST[$prefix.'mon']))
			$getdate['mon']=intval($_POST[$prefix.'mon']);
		else if (isset($_POST[$prefix.'month']))
			$getdate['mon']=intval($_POST[$prefix.'month']);
		else $getdate['mon']=0;
		if (isset($_POST[$prefix.'mday']))
			$getdate['mday']=intval($_POST[$prefix.'mday']);
		else $getdate['mday']=0;
		if (isset($_POST[$prefix.'year']))
			$getdate['year']=intval($_POST[$prefix.'year']);
		else $getdate['year']=0;

		// enregistrement comme derniere date utilisee
		$this->date=$getdate;
		if ($format_sortie=="php_getdate") return $getdate;
		return $this->_convertTo($getdate,$format_sortie);
	}
/*---------------------------------------------------------------------------
fonctions de calcul sur les dates
exclusivement sur les dates valides timestamp unix actuellement
---------------------------------------------------------------------------*/

	// ajout de deux dates
	function add($left, $right, $outputFormat=NULL) {
		// conversions des deux dates en getdate
		$leftFormat=$this->_getFormat($left);
		if ($leftFormat!="php_getdate")
			$left=$this->_convertFrom($left,$leftFormat);
		$rightFormat=$this->_getFormat($right);
		if ($rightFormat!="php_getdate")
			$right=$this->_convertFrom($right,$rightFormat);
		// calcul en cascade
		if (($left['seconds']+=$right['seconds'])>59) {
			$left['seconds']-=60; $left['minutes']+=1;
		}
		if (($left['minutes']+=$right['minutes'])>59) {
			$left['minutes']-=60; $left['hours']+=1;
		}
		if (($left['hours']+=$right['hours'])>23) {
			$left['hours']-=24; $left['mday']+=1;
		}
		if (($left['mday']+=$right['mday'])>($j=$this->_daysInMonth($left))) {
			$left['mon']+=1; $left['mday']-=$j;
		}
		if (($left['mon']+=$right['mon'])>12) {
			$left['mon']-=12; $left['year']+=1;
		}
		$left['year']+=$right['year'];
		if ($outputFormat===NULL) $outPutFormat=$leftFormat;
		return $this->_convertTo($left,$outputFormat);
	}

	// soustraction de deux dates. Le resultat est au format de la date de gauche
	function soustract($left, $right,$outputFormat=NULL) {
		// conversions des deux dates en getdate
		$leftFormat=$this->_getFormat($left);
		if ($leftFormat!="php_getdate")
			$left=$this->_convertFrom($left,$leftFormat);
		$rightFormat=$this->_getFormat($right);
		if ($rightFormat!="php_getdate")
			$right=$this->_convertFrom($right,$rightFormat);
		// calcul en cascade
		if (($left['seconds']-=$right['seconds'])<0) {
			$left['seconds']+=60; $left['minutes']-=1;
		}
		if (($left['minutes']-=$right['minutes'])<0) {
			$left['minutes']+=60; $left['hours']-=1;
		}
		if (($left['hours']-=$right['hours'])<0) {
			$left['hours']+=24; $left['mday']-=1;
		}
		if (($left['mday']-=$right['mday'])<1) {
			$left['mon']-=1; $left['mday']+=$this->_daysInMonth($left);
		}
		if (($left['mon']-=$right['mon'])<1) {
			$left['mon']+=12; $left['year']-=1;
		}
		$left['year']-=$right['year'];
		if ($outputFormat===NULL) $outputFormat=$leftFormat;
		return $this->_convertTo($left,$outputFormat);
	}

/*---------------------------------------------------------------------------
                                                             methodes privées
---------------------------------------------------------------------------*/

	// tente de determiner le format d'une date
	function _getFormat($date) {
		switch (true) {
			case is_integer($date) and $date>0 and $date<2147483647:
				return "php_timestamp";
				break;
			case is_array($date) and isset($date['year']) and isset($date['mon']) and isset($date['mday'])
			and isset($date['hours']) and isset($date['seconds']) and isset($date['minutes']):
				return "php_getdate";
				break;
			case ereg ('^[0-9]{4}-((0[1-9])|(1[0-2]))-((0[1-9])|([1-2][0-9])|(3[0-1]))$', $date):
				return "mysql_date";
				break;
			case ereg ('^[0-9]{4}-((0[1-9])|(1[0-2]))-((0[1-9])|([1-2][0-9])|(3[0-1])) '
			.'(([0-1][0-9])|(2[0-3]))(:[0-5][0-9]){2}$', $date):
				return "mysql_datetime";
				break;
			case ereg ('^[0-9]{14}$', $date):
				return "mysql_timestamp";
				break;
			// ce qui suit permet des dates incorrectes type 0000-00-00
			case ereg ('^[0-9]{4}-((0[0-9])|(1[0-2]))-((0[0-9])|([1-2][0-9])|(3[0-1]))$', $date):
				return "mysql_date";
				break;
			case ereg ('^[0-9]{4}-((0[0-9])|(1[0-2]))-((0[0-9])|([1-2][0-9])|(3[0-1])) '
			.'(([0-1][0-9])|(2[0-3]))(:[0-5][0-9]){2}$', $date):
				return "mysql_datetime";
				break;
			case ereg('^((0?[0-9])|([1-2][0-9])|(3[0-1]))/((0?[0-9])|(1[0-2]))/[0-9]{2,4}$', $date):
				return 'fr_date';
				break;
			default:
				trigger_error("timeManager unkown date format for $date",E_USER_NOTICE);
				return false;
				break;
		}
	}

	// convertit vers le format php_getdate
	function _convertFrom($date,$format) {
		if ($format=="php_getdate") return $date;
		if (!isset($this->formats[$format]['from'])) {
			trigger_error("timeManager: input date format $format is not handled, handled formats are : ".join(' ',array_keys($this->formats)),E_USER_NOTICE);
			return false;
		}
		// determination de la methode
		$method=$this->formats[$format]['from'];
		$getdate=$this->$method($date);
		return $getdate;
	}

	// convertit un php_getdate au format dÚsirÚ
	function _convertTo($getdate,$format) {
		if ($format=="php_getdate") return $getdate;
		if (!isset($this->formats[$format]['to'])) {
			trigger_error("timeManager: output date format $format is not handled, handled formats are : ".join(' ',array_keys($this->formats)),E_USER_NOTICE);
			return false; // le format n'est pas reconnu
		}
		// determination de la methode
		$method=$this->formats[$format]['to'];
		return $this->$method($getdate);
	}

	function _fromPhpTimestamp($time) {
		$date=@getdate($time);
		return $date;
	}

	function _fromPhpGetDate($getdate) {
		return $getdate;
	}

	function _fromMysqlDate($date) {
		$date=explode("-",$date);
		if (!count($date)==3) {
			$this->trigger_error("format mysql_date incorrect : $date",E_USER_NOTICE);
			return false;
		}
		$getdate=array(
			"seconds" => 0,
			"minutes" => 0,
			"hours" => 0,
			"mday" => intval($date[2]),
			"wday" => 0,
			"mon" => intval($date[1]),
			"year" => intval($date[0]),
			"yday" => 0,
			"weekday" => "",
			"month" => $this->mois[intval($date[1])]);
		return $getdate;
	}
	
	function _fromFrDate($strdate) {
		$date=explode("/",$strdate);
		if (!count($date)==3) {
			$this->trigger_error("format fr_date incorrect : $strdate",E_USER_NOTICE);
			return false;
		}
		$getdate=array(
			"seconds" => 0,
			"minutes" => 0,
			"hours" => 0,
			"mday" => intval($date[0]),
			"wday" => 0,
			"mon" => intval($date[1]),
			"year" => intval($date[2]),
			"yday" => 0,
			"weekday" => "",
			"month" => $this->mois[intval($date[1])]);
		return $getdate;
	}

	function _fromMysqlDateTime($datetime) {
		/*$hours=intval(substr($datetime,11,2));
		$minutes=intval(substr($datetime,14,2));
		$seconds=intval(substr($datetime,17,2));
		$mday=intval(substr($datetime,8,2));
		$mon=intval(substr($datetime,5,2));
		$year=intval(substr($datetime,0,4));*/
		$getdate=array(
			"seconds" => intval(substr($datetime,17,2)),
			"minutes" => intval(substr($datetime,14,2)),
			"hours" => intval(substr($datetime,11,2)),
			"mday" => intval(substr($datetime,8,2)),
			"wday" => 0,
			"mon" => intval(substr($datetime,5,2)),
			"year" => intval(substr($datetime,0,4)),
			"yday" => 0,
			"weekday" => "",
			"month" => $this->mois[intval(substr($datetime,5,2))]);
		return $getdate;
	}

	function _fromMysqlTimestamp($mysql_timestamp) {
		$mysql_timestamp=strval($mysql_timestamp);
		if (!strlen($mysql_timestamp)==14) return false;
		$year=intval(substr($mysql_timestamp,0,4));
		$mon=intval(substr($mysql_timestamp,4,2));
		$mday=intval(substr($mysql_timestamp,6,2));
		$hours=intval(substr($mysql_timestamp,8,2));
		$minutes=intval(substr($mysql_timestamp,10,2));
		$seconds=intval(substr($mysql_timestamp,12,2));
		$getdate=array(
			"seconds" => $seconds,
			"minutes" => $minutes,
			"hours" => $hours,
			"mday" => $mday,
			"wday" => 0,
			"mon" => $mon,
			"year" => $year,
			"yday" => 0,
			"weekday" => "",
			"month" => $this->mois[intval($mon)]);
		return $getdate;
	}

	function _toPhpTimestamp($getdate) {
		$retour=@mktime($getdate['hours'],$getdate['minutes'],$getdate['seconds']
			,$getdate['mon'],$getdate['mday'],$getdate['year']);
		if ($retour<0)
			trigger_error("conversion en timestamp impossible : date anterieure a la periode Unix",E_USER_NOTICE);
		return $retour;
	}

	function _toPhpGetDate($getdate) {
		return $getdate;
	}

	function _toMysqlDate($getdate) {
		return sprintf("%04d",$getdate['year'])."-".sprintf("%02d",$getdate['mon'])."-".sprintf("%02d",$getdate['mday']);
	}
	
	function _toFrDate($getdate) {
		return sprintf("%02d",$getdate['mday']).'/'.sprintf("%02d",$getdate['mon']).'/'.sprintf("%04d",$getdate['year']);
	}

	function _toMysqlDateTime($getdate) {
		return $getdate['year']."-".sprintf("%02d",$getdate['mon'])."-".sprintf("%02d",$getdate['mday'])
		." ".sprintf("%02d",$getdate['hours']).":".sprintf("%02d",$getdate['minutes']).":"
		.sprintf("%02d",$getdate['seconds']);
	}

	function _toMysqlTimestamp($time) {
		return $getdate['year'].sprintf("%02d",$getdate['mon']).sprintf("%02d",$getdate['mday'])
		.sprintf("%02d",$getdate['hours']).sprintf("%02d",$getdate['minutes']).sprintf("%02d",$getdate['seconds']);
	}

	// fonctions de determinations du nombre de jours dans un mois et une annee
	function _daysInMonth($getdate) {
		// fonction trouvee sur internet
		if ($getdate['mon']==2) {
			if ($getdate['year']%4) return 28;
			elseif ($getdate['year']%100) return 29;
			elseif ($getdate['year']%1000) return 28;
			else return 29;
		} elseif ($getdate['mon']==4 or $getdate['mon']==6 or $getdate['mon']==9 or $getdate['mon']==11) return 30;
		return 31;
	}

	function _daysInYear($getdate) {
		return 337 + DaysInMonth(2,$getdate['year']);
	}

	/*function _error($txt) {
		$this->log[]=array(
			"class" => "datetool",
			"time" => time(),
			"type" => "error",
			"txt" => $txt);
	}

	function _action($txt) {
		$this->log[]=array(
			"class" => "datetool",
			"time" => time(),
			"type" => "action",
			"txt" => $txt);
	}*/
/*-------------------------------------------------------------------------------------------------
                                                                                   fin de la classe
-------------------------------------------------------------------------------------------------*/
}
?>
